import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

import org.biojava3.core.sequence.RNASequence;
import org.biojava3.core.sequence.compound.NucleotideCompound;

public class PrintData {
	private RNASequence referenceSequence = null;
	private LinkedList<Site> sequenceSites = null;
	private double abundanceLimit = 0.99;
	
	public PrintData (LinkedList<Site> sequenceSites, RNASequence referenceSequence) {
		this.sequenceSites = sequenceSites;
		this.referenceSequence = referenceSequence;
	}
	
	public void printEverything() {
		//String fileEntropy = "eukEntropy";
		String fileEntropy = "prokEntropy";
		printEntropy(fileEntropy);
		//String fileMostFrequentNucleotide = "eukMostFrequentNucleotide";
		String fileMostFrequentNucleotide = "prokMostFrequentNucleotide";
		printMostFrequentNucleotide(fileMostFrequentNucleotide);
		//String fileSecMostFrequentNucleotide = "eukSecMostFrequentNucleotide";
		String fileSecMostFrequentNucleotide = "prokSecMostFrequentNucleotide";
		printSecondMostFrequentNucleotide(fileSecMostFrequentNucleotide);
		//String fileThirdMostFrequentNucleotide = "eukThirdMostFrequentNucleotide";
		String fileThirdMostFrequentNucleotide = "prokThirdMostFrequentNucleotide";
		printThirdMostFrequentNucleotide(fileThirdMostFrequentNucleotide);
		//String fileGaps = "eukGaps";
		String fileGaps = "prokGaps";
		printGaps(fileGaps);
		String fileStatRef = "stat_" + referenceSequence.getTaxonomy().getSilvaName();
		printStatDataToReference(fileStatRef);
		String fileNuclRef = "nucl_" + referenceSequence.getTaxonomy().getSilvaName();
		printNuclDataToReference(fileNuclRef);
		double abundanceCounter = 0.99;
		while (abundanceCounter <= abundanceLimit) {
			String fileCheckGapsRef = "gapsref_" + abundanceCounter;
			checkRepresentationOfReference(fileCheckGapsRef, abundanceCounter);
			abundanceCounter += 0.01;
		}
	}
	
	public void printStatDataToReference(String fileStatRef) {
		RNASequence refSequence = referenceSequence;
		Iterator<NucleotideCompound> seqIter = refSequence.iterator();
		Iterator<Site> siteIter = sequenceSites.listIterator();
		PrintWriter stat = null;
		try {
			stat = new PrintWriter(fileStatRef);
			stat.println("Entropy"+"\t"+"MostFreq"+"\t"+"SecMostFreq"+"\t"+"ThirdMostFreq"+"\t"+"Gaps");
			while (seqIter.hasNext() && siteIter.hasNext()) {
				NucleotideCompound currentNucleotide = seqIter.next();
				Site currentSite = siteIter.next();
				if (!(currentNucleotide.getBase().equalsIgnoreCase(".")) && !(currentNucleotide.getBase().equalsIgnoreCase("-"))) {
					stat.println(currentSite.getEntropy()+"\t"+currentSite.getRelativeAbundance(currentSite.getMostFrequentNucleotide())+"\t"+
							currentSite.getRelativeAbundance(currentSite.getSecondMostFrequentNucleotide())+"\t"+
							currentSite.getRelativeAbundance(currentSite.getThirdMostFrequentNucleotide())+"\t"+
							currentSite.getGaps());
				}
			}
			stat.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void printNuclDataToReference(String fileNuclRef) {
		RNASequence refSequence = referenceSequence;
		Iterator<NucleotideCompound> seqIter = refSequence.iterator();
		Iterator<Site> siteIter = sequenceSites.listIterator();
		PrintWriter nucl = null;
		try {
			nucl = new PrintWriter(fileNuclRef);
			nucl.println("MostFreq"+"\t"+"SecMostFreq"+"\t"+"ThirdMostFreq"+"\t"+referenceSequence.getTaxonomy().getSilvaName());
			while (seqIter.hasNext() && siteIter.hasNext()) {
				NucleotideCompound currentNucleotide = seqIter.next();
				Site currentSite = siteIter.next();
				if (!(currentNucleotide.getBase().equalsIgnoreCase(".")) && !(currentNucleotide.getBase().equalsIgnoreCase("-"))) {
					nucl.println(currentSite.getMostFrequentNucleotide().getBase()+"\t"+currentSite.getSecondMostFrequentNucleotide()+"\t"+
							currentSite.getThirdMostFrequentNucleotide().getBase()+"\t"+currentNucleotide.getBase());
				}
			}
			nucl.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public void printGaps(String fileGaps) {
		PrintWriter printer = null;
		try {
			printer = new PrintWriter(fileGaps);
			printer.println("Abundance");
			for (ListIterator<Site> iterSites = sequenceSites.listIterator(); iterSites.hasNext();) {
				int index = iterSites.nextIndex();
				Site currentSite = iterSites.next();
				printer.println(index + "\t" + currentSite.getGaps());
			}
			printer.close();
		} catch (FileNotFoundException e) {
			System.out.println("File " + fileGaps + " not found!");
			e.printStackTrace();
		}
	}
	
	public void printMostFrequentNucleotide(String fileMostFrequentNucleotide) {
		PrintWriter printer = null;
		try {
			printer = new PrintWriter(fileMostFrequentNucleotide);
			printer.println("Nucleotide" + "\t" + "Abundance");
			for (ListIterator<Site> iterSites = sequenceSites.listIterator(); iterSites.hasNext();) {
				int index = iterSites.nextIndex();
				Site currentSite = iterSites.next();
				printer.println(index + "\t" + currentSite.getMostFrequentNucleotide().getBase() + "\t" + currentSite.getRelativeAbundance(currentSite.getMostFrequentNucleotide()));
			}
			printer.close();
		} catch (FileNotFoundException e) {
			System.out.println("File " + fileMostFrequentNucleotide + " not found!");
			e.printStackTrace();
		}
	}
	
	public void printSecondMostFrequentNucleotide(String fileSecMostFrequentNucleotide) {
		PrintWriter printer = null;
		try {
			printer = new PrintWriter(fileSecMostFrequentNucleotide);
			printer.println("Nucleotide" + "\t" + "Abundance");
			for (ListIterator<Site> iterSites = sequenceSites.listIterator(); iterSites.hasNext();) {
				int index = iterSites.nextIndex();
				Site currentSite = iterSites.next();
				if (currentSite.getSecondMostFrequentNucleotide() == null)
					printer.println(index + "\t" + "*" + "\t" + 0);
				else
					printer.println(index + "\t" + currentSite.getSecondMostFrequentNucleotide().getBase() + "\t" + currentSite.getRelativeAbundance(currentSite.getSecondMostFrequentNucleotide()));
			}
			printer.close();
		} catch (FileNotFoundException e) {
			System.out.println("File " + fileSecMostFrequentNucleotide + " not found!");
			e.printStackTrace();
		}
	}
	
	public void printThirdMostFrequentNucleotide(String fileThirdMostFrequentNucleotide) {
		PrintWriter printer = null;
		try {
			printer = new PrintWriter(fileThirdMostFrequentNucleotide);
			printer.println("Nucleotide" + "\t" + "Abundance");
			for (ListIterator<Site> iterSites = sequenceSites.listIterator(); iterSites.hasNext();) {
				int index = iterSites.nextIndex();
				Site currentSite = iterSites.next();
				if (currentSite.getThirdMostFrequentNucleotide() == null)
					printer.println(index + "\t" + "*" + "\t" + 0);
				else
					printer.println(index + "\t" + currentSite.getThirdMostFrequentNucleotide().getBase() + "\t" + currentSite.getRelativeAbundance(currentSite.getThirdMostFrequentNucleotide()));
			}
			printer.close();
		} catch (FileNotFoundException e) {
			System.out.println("File " + fileThirdMostFrequentNucleotide + " not found!");
			e.printStackTrace();
		}
	}
	
	public void printEntropy(String file) {
		PrintWriter printer = null;
		try {
			printer = new PrintWriter(file);
			printer.println("Entropy");
			for (ListIterator<Site> iterSites = sequenceSites.listIterator(); iterSites.hasNext();) {
				printer.println(iterSites.next().getEntropy());
			}
			printer.close();
		} catch(FileNotFoundException e) {
			System.out.println("File " + file + " not found!");
			e.printStackTrace();
		}
	}
	
	public void checkRepresentationOfReference(String repFile, double abundanceLimit) {
		RNASequence refSequence = referenceSequence;
		Iterator<NucleotideCompound> seqIter = refSequence.iterator();
		Iterator<Site> siteIter = sequenceSites.listIterator();
		PrintWriter rep = null;
		int refIndex = 0;
		int siteIndex = 0;
		try {
			rep = new PrintWriter(repFile);
			rep.println("refIndex"+"\t"+"siteIndex"+"\t"+"gapAbundance");
			while (seqIter.hasNext() && siteIter.hasNext()) {
				NucleotideCompound currentNucleotide = seqIter.next();
				Site currentSite = siteIter.next();
				siteIndex++;
				if (!(currentNucleotide.getBase().equalsIgnoreCase(".")) && !(currentNucleotide.getBase().equalsIgnoreCase("-"))) {
					refIndex++;
				}
				else if (currentSite.getGaps() < abundanceLimit) {
					rep.println(refIndex+"\t"+siteIndex+"\t"+currentSite.getGaps());
				}
			}
			rep.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}
